#define MM_MAPS_MANAGER_INCLUDED 1

#if !defined MM_GLOBALS_INCLUDED
#include "include/mm_globals.inl"
#endif

#define MM_ADD_MAP 1
#define MM_DEL_MAP 2
#define MM_EDIT_MAP 3
#define MM_SAVE_INI 4

new gMainMenu;
new gPlayersMenuPos[MAX_PLAYERS];

new gPlayersAddMapName[MAX_PLAYERS][MAP_NAME_LEN];
new gPlayersEditMapId[MAX_PLAYERS];
new gPlayersAddMapMin[MAX_PLAYERS];
new gPlayersAddMapMax[MAX_PLAYERS];

stock plugin_init_mapsManager(){
	register_clcmd("mm_refreshmaps", "userRefreshMaps", ADMIN_CVAR);
	register_clcmd("mm_mapsmenu", "mmMapsMenu", ADMIN_CVAR);
	register_srvcmd("mm_refreshmaps", "userRefreshMaps");
	register_clcmd("mm_add_map_name", "mmAddMapName", ADMIN_CVAR);
	register_clcmd("mm_add_map_min", "mmAddMapMin", ADMIN_CVAR);
	register_clcmd("mm_add_map_max", "mmAddMapMax", ADMIN_CVAR);
	new val[4];
	new timestamp;
	if(nvault_lookup(gVault, mmKeyMapsCount, val, 3, timestamp)){
		gAllMapsCount = str_to_num(val);
	} else {
		refreshMaps(0);
	}
}

public mmMapsMenu(id, level,cid){
	if(!get_pcvar_num(gCvarActive))
		return PLUGIN_CONTINUE;
	if(cmd_access(id,level,cid, 0)){
		showMainMenu(id);
	}
	return PLUGIN_HANDLED;
}
showMainMenu(id){
	if(!gMainMenu){
		new title[32];
		formatex(title, charsmax(title), "%L", LANG_PLAYER, "TITLE_MAP_MANAGER");
		gMainMenu = menu_create(title, "mainMenuHandler");
		new info[2];
		info[1] = 1;
		
		formatex(title, charsmax(title), "%L", LANG_PLAYER, "TITLE_MAP_MANAGER_ADD_MAP");
		info[0] = MM_ADD_MAP;
		menu_additem(gMainMenu, title, info);
		
		formatex(title, charsmax(title), "%L", LANG_PLAYER, "TITLE_MAP_MANAGER_DEL_MAP");
		info[0] = MM_DEL_MAP;
		menu_additem(gMainMenu, title, info);
		
		formatex(title, charsmax(title), "%L", LANG_PLAYER, "TITLE_MAP_MANAGER_EDIT_MAP");
		info[0] = MM_EDIT_MAP;
		menu_additem(gMainMenu, title, info);
		
		formatex(title, charsmax(title), "%L", LANG_PLAYER, "TITLE_MAP_MANAGER_SAVE_INI");
		info[0] = MM_SAVE_INI;
		menu_additem(gMainMenu, title, info);
	}
	menu_display(id, gMainMenu);
}

public mainMenuHandler(id, menu, item){
	if(item ==MENU_EXIT){
		show_menu(id, 0, "^n");
	} else {
		new callback, acc;
		new info[2];
		new itemId;
		menu_item_getinfo(menu, item, acc, info, 1, _, _, callback);
		itemId = info[0];
		gPlayersMenuPos[id] = itemId;
		switch(itemId){
			case MM_ADD_MAP: client_cmd(id, "messagemode mm_add_map_name");
			case MM_EDIT_MAP, MM_DEL_MAP: showMapChooseMenu(id);
			case MM_SAVE_INI: {
				rewriteIniFile(id);
				client_print(id, print_chat, "%L", LANG_PLAYER, "INI_WRITTEN");
				showMainMenu(id);
			}
		}
	}
}

stock showMapChooseMenu(id){
	new title[MAP_NAME_LEN +20];
	formatex(title, charsmax(title), "%L", LANG_PLAYER, "TITLE_MAP_CHOOSE");
	new menu = menu_create(title, "mapsMenuHandler");
	
	new itm[2];
	new map[MAP_NAME_LEN];
	new mapId, minP, maxP;
	
	for(new i=0;i<gAllMapsCount;i++){
		getMapNameById(i, map);
		isMapValid(map, 0,0,0, mapId, map, minP,maxP);
		formatex(title, charsmax(title), "%s Id:%d, Min:%d, Max:%d", map, mapId, minP, maxP);
		itm[0] = i;
		menu_additem(menu, title, itm);
	}
	
	menu_display(id, menu);
}

public mapsMenuHandler(id, menu, item){
	if(item == MENU_EXIT){
		menu_destroy(menu);
		menu_display(id, gMainMenu);
	} else { 
		if(item != MENU_BACK && item != MENU_MORE){
			new info[2];
			new acc,callback;
			new name[MAP_NAME_LEN +20];
			menu_item_getinfo(menu, item, acc, info, 1, name, charsmax(name), callback);
			
			if(gPlayersMenuPos[id] == MM_EDIT_MAP){
				gPlayersEditMapId[id] = info[0];
				client_cmd(id, "messagemode mm_add_map_min");
				client_print(id, print_chat, name);
			} else { //delete map
				removeMapById(id, info[0]);
			}
			menu_destroy(menu);
			showMapChooseMenu(id);
		}
	}
}

stock mapExists(map[MAP_NAME_LEN]){
	new mapFile[MAP_NAME_LEN + 10];
	replace_all(map, MAP_NAME_LEN-1, ".bsp", "");
	//return is_map_valid(map);
	formatex(mapFile, charsmax(mapFile), "maps/%s.bsp", map);
	//return 1;
	return file_exists(mapFile);
}

public mmAddMapName(id, level, cid){
	if(!get_pcvar_num(gCvarActive))
		return PLUGIN_CONTINUE;
	if(gPlayersMenuPos[id] != MM_ADD_MAP  &&  gPlayersMenuPos[id] != MM_EDIT_MAP){
		client_print(id, print_console, "%L", LANG_PLAYER, "CONNAMD_NOT_VALID");
		client_print(id, print_chat, "%L", LANG_PLAYER, "CONNAMD_NOT_VALID");
		return PLUGIN_HANDLED;
	}
	gPlayersAddMapName[id][0] = 0;
	gPlayersAddMapMin[id] = 0;
	gPlayersAddMapMax[id] = 0;
	if(cmd_access(id,level,cid, 1)){
		new map[MAP_NAME_LEN];
		read_argv(1, map, MAP_NAME_LEN -1);
		if(!mapExists(map)){
			client_print(id, print_console, "%L", LANG_PLAYER, "MAP_DOES_NOT_EXIST");
			client_print(id, print_chat, "%L", LANG_PLAYER, "MAP_DOES_NOT_EXIST");
		} else {
			copy(gPlayersAddMapName[id], MAP_NAME_LEN -1, map);
			client_cmd(id, "messagemode mm_add_map_min");
		}
	}

	return PLUGIN_HANDLED;
}


public mmAddMapMin(id, level, cid){
	if(!get_pcvar_num(gCvarActive))
		return PLUGIN_CONTINUE;
	if(gPlayersMenuPos[id] != MM_ADD_MAP  &&  gPlayersMenuPos[id] != MM_EDIT_MAP){
		client_print(id, print_console, "%L", LANG_PLAYER, "CONNAMD_NOT_VALID");
		client_print(id, print_chat, "%L", LANG_PLAYER, "CONNAMD_NOT_VALID");
		return PLUGIN_HANDLED;
	}
	if(cmd_access(id,level,cid, 1)){
		new minP[3];
		read_argv(1, minP, charsmax(minP));
		if(!is_str_num(minP)){
			client_print(id, print_console, "%L", LANG_PLAYER, "INVALID_NUMBER");
			client_print(id, print_chat, "%L", LANG_PLAYER, "INVALID_NUMBER");
		} else {
			gPlayersAddMapMin[id] = str_to_num(minP);
			client_cmd(id, "messagemode mm_add_map_max");
		}
	}
	return PLUGIN_HANDLED;
}


public mmAddMapMax(id, level, cid){
	if(!get_pcvar_num(gCvarActive))
		return PLUGIN_CONTINUE;
	new menuPos =gPlayersMenuPos[id];
	if( menuPos!= MM_ADD_MAP  &&  menuPos != MM_EDIT_MAP){
		client_print(id, print_console, "%L", LANG_PLAYER, "CONNAMD_NOT_VALID");
		client_print(id, print_chat, "%L", LANG_PLAYER, "CONNAMD_NOT_VALID");
		return PLUGIN_HANDLED;
	}
	if(cmd_access(id,level,cid, 1)){
		new maxP[3];
		read_argv(1, maxP, charsmax(maxP));
		if(!is_str_num(maxP)){
			client_print(id, print_console, "%L", LANG_PLAYER, "INVALID_NUMBER");
			client_print(id, print_chat, "%L", LANG_PLAYER, "INVALID_NUMBER");
		} else {
			gPlayersAddMapMax[id] = str_to_num(maxP);
			saveUserCahnges(id);
		}
	}
	if(menuPos == MM_ADD_MAP)
		showMainMenu(id);
	else
		showMapChooseMenu(id);
	return PLUGIN_HANDLED;
}

stock saveUserCahnges(id){
	if(gPlayersAddMapName[id][0]){
		saveMap(id, gPlayersAddMapName[id], gAllMapsCount, gPlayersAddMapMin[id], gPlayersAddMapMax[id]);
		gAllMapsCount++;
	} else  {
		new mapId = gPlayersEditMapId[id];
		if(mapId != NO_MAP){
			new map[MAP_NAME_LEN];
			if(getMapNameById(mapId, map)){
				saveMap(id, map, mapId, gPlayersAddMapMin[id], gPlayersAddMapMax[id]);
			}
		}
	}
}

public userRefreshMaps(id, level, cid){
	if(!get_pcvar_num(gCvarActive))
		return PLUGIN_CONTINUE;
	if(!id || cmd_access(id,level,cid,0)){
		refreshMaps(id);
	}
	return PLUGIN_HANDLED;
}

public refreshMaps(id) {
	if(gMapVoteStarted){
		log_to_file(mmLogFile, "%L", LANG_SERVER, "CANNOT_EDIT");
		if(id)	{
			client_print(id, print_console, "%L", LANG_PLAYER, "CANNOT_EDIT");
		}
		return;
	}
	
	new mapInfo[MAP_NAME_LEN + 8];
	new map[MAP_NAME_LEN];
	new minP[4];
	new maxP[4];
	new mapId[4];
	new timestamp;
	new tmpInfo[10];
	
	new name[MAX_NAME_LEN];
	get_user_name(id, name, MAX_NAME_LEN -1);
	new steam[MAX_NAME_LEN];
	get_user_authid(id, steam, MAX_NAME_LEN -1);
	
	log_to_file(mmLogFile, "USER %s [%s] is Refreshing all maps", name, steam);
	
	
	if(gVault){ //Remove old maps
		for(new i=0;i< gAllMapsCount;i++){
			num_to_str(i, mapId, charsmax(mapId));
			getMapNameById(i, map);
			nvault_remove(gVault, mapId);
			nvault_remove(gVault, map);
		}
		nvault_close(gVault);
		gVault = nvault_open(mapManagementVault);
	}
	new cfg[64];
	get_configsdir(cfg, charsmax(cfg));
	format(cfg, charsmax(cfg), "%s/mm_maps.ini", cfg);
	new file = fopen(cfg, "r");
	if(!file){
		log_to_file(mmLogFile, "NO mm_maps.ini File in configs dir");
		set_fail_state("NO mm_maps.ini File in configs dir!");
	}
		
	gAllMapsCount = 0;
	new minPlayers, maxPlayers;
	while(!feof(file)) {
		fgets(file,mapInfo,charsmax(mapInfo));
		trim(mapInfo);
	
		if(mapInfo[0] == 0 || mapInfo[0] == ';')
			continue;
		parse(mapInfo, map, MAP_NAME_LEN-1, minP, 3, maxP, 3);
		strtolower(map);
		
		if(!is_str_num(minP) || !is_str_num(maxP)){
			log_to_file(mmLogFile, "Bad Format: %s",  mapInfo);
			continue;
		}
		if(nvault_lookup(gVault, map, tmpInfo, charsmax(tmpInfo), timestamp)){
			log_to_file(mmLogFile, "Duplicated Map: %s", map);
			continue;
		}
		minPlayers = str_to_num(minP);
		maxPlayers = str_to_num(maxP);
		
		if(mapExists(map) ) 
		{
			saveMap(id, map, gAllMapsCount, minPlayers, maxPlayers);			
			gAllMapsCount++;
		}
	}
	
	log_to_file(mmLogFile, "USER %s [%s] Refreshed all maps", name, steam);
	
	fclose(file);
	num_to_str(gAllMapsCount, mapId, 3);
	nvault_set(gVault, mmKeyMapsCount, mapId);
}

stock removeMapById(id, map){
	new mapName[MAP_NAME_LEN];
	if(getMapNameById(map, mapName)){
		removeMap(id, mapName);
	}
}

stock removeMap(id, const map[MAP_NAME_LEN]){
	new mapId, minP, maxP;
	new mapRealName[MAP_NAME_LEN];
	new nextMap;
	new nextMapName[MAP_NAME_LEN];
	new mapIdS[4];
	if(isMapValid(map, 0,0,0, mapId, mapRealName, minP, maxP) == MAP_VALID_FOR_NOMINATION){
		num_to_str(mapId, mapIdS, charsmax(mapIdS));
		nvault_remove(gVault, mapRealName);
		nvault_remove(gVault, mapIdS);
		if(id){
			client_print(id, print_console, "%L", LANG_PLAYER, "MAP_REMOVED", map, mapIdS);
			client_print(id, print_chat, "%L", LANG_PLAYER, "MAP_REMOVED", map, mapIdS);
		}
		for(new i=mapId+1;i< gAllMapsCount;i++){
			getMapNameById(i, nextMapName);
			isMapValid(nextMapName, 0,0,0, nextMap, nextMapName, minP, maxP);
			nvault_remove(gVault, nextMapName);
			saveMap(0, nextMapName, i-1, minP, maxP);
		}
		gAllMapsCount--;
		num_to_str(gAllMapsCount, mapIdS, charsmax(mapIdS));
		nvault_set(gVault, mmKeyMapsCount, mapIdS);
		nvault_close(gVault);
		gVault = nvault_open(mapManagementVault);
		
		new name[MAX_NAME_LEN];
		get_user_name(id, name, MAX_NAME_LEN -1);
		new steam[MAX_NAME_LEN];
		get_user_authid(id, steam, MAX_NAME_LEN -1);
		
		log_to_file(mmLogFile, "USER %s [%s] Deleted map %s", name,  steam, mapRealName);
	}
}

stock saveMap(id, const map[MAP_NAME_LEN], mapId, minPlayers, maxPlayers){
	new mapInfo[MAP_NAME_LEN + 8];
	formatex(mapInfo, charsmax(mapInfo), "%d %d %d", mapId, minPlayers, maxPlayers);
	new mapIdStr[4];
	num_to_str(mapId, mapIdStr, charsmax(mapIdStr));
	nvault_set(gVault, mapIdStr, map);
	nvault_set(gVault, map, mapInfo);
	new oldMapId, oldMinP, oldMaxP;
	new realName[MAP_NAME_LEN];
	
	new name[MAX_NAME_LEN];
	get_user_name(id, name, MAX_NAME_LEN -1);
	new steam[MAX_NAME_LEN];
	get_user_authid(id, steam, MAX_NAME_LEN -1);
	
	if(isMapValid(map, 0,0,0, oldMapId, realName, oldMinP, oldMaxP)){
		log_to_file(mmLogFile, "USER %s [%s] Modified map %s", name,steam, map);
		log_to_file(mmLogFile,"OLD: [ID=%d, MIN=%d, MAX=%d] NEW: [ID=%d, MIN=%d, MAX=%d]",oldMapId, oldMinP, oldMaxP, mapId, minPlayers, maxPlayers);
	} else {
		log_to_file(mmLogFile, "USER %s [%s] Added map %s [ID=%d, MIN=%d, MAX=%d]", name,steam, map, mapId, minPlayers, maxPlayers);
	}
	
	if(id){
		client_print(id, print_console, "%L", LANG_PLAYER, "MAP_SAVED", map, mapId, minPlayers, maxPlayers);
		client_print(id, print_chat, "%L", LANG_PLAYER, "MAP_SAVED", map, mapId, minPlayers, maxPlayers);
	}
}

stock rewriteIniFile(id) {
	new minP, maxP, mapId;
	new map[MAP_NAME_LEN];
	
	new cfg[64];
	get_configsdir(cfg, charsmax(cfg));
	format(cfg, charsmax(cfg), "%s/mm_maps.ini", cfg);
	delete_file(cfg);
	
	new line[MAP_NAME_LEN + 8];
	
	for (new i=0;i<gAllMapsCount;i++){
		if(getMapNameById(i, map)){
			isMapValid(map, 0 ,0 ,0, mapId, map, minP,maxP);
			formatex(line, charsmax(line), "%s %d %d", map, minP, maxP);
			write_file(cfg, line);
		}
	}
	new name[MAX_NAME_LEN];
	get_user_name(id, name, MAX_NAME_LEN -1);
	new steam[MAX_NAME_LEN];
	get_user_authid(id, steam, MAX_NAME_LEN -1);
	
	log_to_file(mmLogFile, "USER %s [%s] Revrites mm_maps.ini file", name,steam);	
}
